<template>
  <div class="food-safety-container">
    <!-- 顶部标题和工具栏 -->
    <div class="header">
      <div class="header-left">
        <h1>区域食品安全检测分析</h1>
      </div>
      <div class="header-actions">
        <el-select
            v-model="currentIndicator"
            size="small"
            placeholder="选择检测指标"
            @change="handleIndicatorChange"
        >
          <el-option
              v-for="item in indicators"
              :key="item.value"
              :label="item.label"
              :value="item.value"
          />
        </el-select>
        <el-date-picker
            v-model="dateRange"
            type="daterange"
            range-separator="至"
            start-placeholder="开始日期"
            end-placeholder="结束日期"
            size="small"
            @change="handleDateChange"
        />
        <el-button type="primary" size="small" @click="refreshData">
          <el-icon><Refresh /></el-icon>刷新数据
        </el-button>
      </div>
    </div>

    <!-- 关键指标卡片 -->
    <div class="metrics-row">
      <el-card shadow="hover" class="metric-card">
        <div class="metric-content">
          <div class="metric-icon" style="background-color: #f0f7ff;">
            <el-icon color="#409EFF" :size="24">
              <Calendar />
            </el-icon>
          </div>
          <div class="metric-info">
            <div class="metric-title">本月检测量</div>
            <div class="metric-value">{{ metrics.totalTests }}</div>
            <div class="metric-change">
                  <span :class="metrics.testChange >= 0 ? 'up' : 'down'">
                  {{ metrics.testChange >= 0 ? '↑' : '↓' }}
                  {{ Math.abs(metrics.testChange) }}%
                  </span>
              较上月
            </div>
          </div>
        </div>
      </el-card>

      <el-card shadow="hover" class="metric-card">
        <div class="metric-content">
          <div class="metric-icon" style="background-color: #f0f9eb;">
            <el-icon color="#67C23A" :size="24">
              <Check />
            </el-icon>
          </div>
          <div class="metric-info">
            <div class="metric-title">综合合格率</div>
            <div class="metric-value">{{ metrics.passRate }}%</div>
            <div class="metric-change">
                  <span :class="metrics.passRateChange >= 0 ? 'up' : 'down'">
                  {{ metrics.passRateChange >= 0 ? '↑' : '↓' }}
                  {{ Math.abs(metrics.passRateChange) }}%
                  </span>
              较上月
            </div>
          </div>
        </div>
      </el-card>

      <el-card shadow="hover" class="metric-card">
        <div class="metric-content">
          <div class="metric-icon" style="background-color: #fef0f0;">
            <el-icon color="#F56C6C" :size="24">
              <Warning />
            </el-icon>
          </div>
          <div class="metric-info">
            <div class="metric-title">不合格批次</div>
            <div class="metric-value">{{ metrics.abnormalCount }}</div>
            <div class="metric-change">
                  <span :class="metrics.abnormalChange >= 0 ? 'up' : 'down'">
                  {{ metrics.abnormalChange >= 0 ? '↑' : '↓' }}
                  {{ Math.abs(metrics.abnormalChange) }}%
                  </span>
              较上月
            </div>
          </div>
        </div>
      </el-card>

      <el-card shadow="hover" class="metric-card">
        <div class="metric-content">
          <div class="metric-icon" style="background-color: #f0f1f5;">
            <el-icon color="#909399" :size="24">
              <Location />
            </el-icon>
          </div>
          <div class="metric-info">
            <div class="metric-title">检测点数量</div>
            <div class="metric-value">{{ metrics.testPoints }}</div>
            <div class="metric-change">
              覆盖全市{{ metrics.areaCoverage }}个区域
            </div>
          </div>
        </div>
      </el-card>
    </div>

    <!-- 地图和趋势图 -->
    <div class="chart-row">
      <!-- 地图 -->
      <el-card shadow="hover" class="chart-card map-card">
        <template #header>
          <div class="card-header">
            <span>区域检测分布</span>
            <div class="card-actions">
              <el-tag type="info" size="small">检测次数</el-tag>
              <el-tag type="info" size="small">合格率</el-tag>
            </div>
          </div>
        </template>
        <div ref="mapChart" class="map-chart"></div>
        <div class="map-legend">
          <div v-for="(item, index) in legendData" :key="index" class="legend-item">
            <span class="legend-color" :style="{ backgroundColor: item.color }"></span>
            <span class="legend-text">{{ item.name }}</span>
          </div>
        </div>
      </el-card>

      <!-- 趋势图 -->
      <el-card shadow="hover" class="chart-card">
        <template #header>
          <div class="card-header">
            <span>检测趋势分析</span>
            <el-radio-group v-model="trendType" size="small" @change="updateTrendChart">
              <el-radio-button label="day">日趋势</el-radio-button>
              <el-radio-button label="week">周趋势</el-radio-button>
              <el-radio-button label="month">月趋势</el-radio-button>
            </el-radio-group>
          </div>
        </template>
        <div ref="trendChart" class="trend-chart"></div>
      </el-card>
    </div>

    <!-- 检测数据表格 -->
    <el-card shadow="hover" class="table-card">
      <template #header>
        <div class="card-header">
          <span>检测数据明细</span>
          <div class="table-actions">
            <el-input
                v-model="tableSearch"
                placeholder="搜索区域/检测点"
                clearable
                style="width: 200px"
                @clear="handleSearchClear"
            >
              <template #prefix>
                <el-icon>
                  <Search />
                </el-icon>
              </template>
            </el-input>
            <el-button type="primary" plain size="small" @click="exportData">
              <el-icon><Download /></el-icon>导出数据
            </el-button>
          </div>
        </div>
      </template>
      <el-table
          :data="filteredTableData"
          stripe
          style="width: 100%"
          v-loading="loading.table"
          @sort-change="handleSortChange"
      >
        <el-table-column prop="name" label="区域" width="120" fixed sortable />
        <el-table-column label="检测次数" width="120" sortable>
          <template #default="{ row }">
            <el-tag :type="getValueTagType(row.testCount)" size="small">
              {{ row.testCount }}
            </el-tag>
          </template>
        </el-table-column>
        <el-table-column label="合格率" width="150" sortable>
          <template #default="{ row }">
            <el-progress
                :percentage="row.passRate * 100"
                :color="getPassRateColor(row.passRate)"
                :show-text="false"
            />
            <span style="margin-left: 8px">{{ (row.passRate * 100).toFixed(1) }}%</span>
          </template>
        </el-table-column>
        <el-table-column label="不合格批次" width="120" prop="abnormalCount" sortable />
        <el-table-column label="检测点数量" width="120" prop="testPoints" sortable />
        <el-table-column label="操作" width="120" fixed="right" align="center">
          <template #default="{ row }">
            <el-button type="primary" link size="small" @click="showDetail(row)">
              详情
            </el-button>
          </template>
        </el-table-column>
      </el-table>
      <div class="pagination-wrapper">
        <el-pagination
            v-model:current-page="currentPage"
            v-model:page-size="pageSize"
            :page-sizes="[10, 20, 50, 100]"
            layout="total, sizes, prev, pager, next, jumper"
            :total="totalItems"
            @size-change="handleSizeChange"
            @current-change="handlePageChange"
        />
      </div>
    </el-card>

    <!-- 区域详情对话框 -->
    <el-dialog
        v-model="detailVisible"
        :title="`${currentArea.name} - 食品安全检测详情`"
        width="80%"
        top="5vh"
    >
      <div class="detail-container">
        <div class="detail-chart">
          <div ref="detailChart" class="chart"></div>
        </div>
        <div class="detail-info">
          <el-tabs v-model="detailTab" class="detail-tabs">
            <el-tab-pane label="基本信息" name="basic">
              <el-descriptions :column="2" border>
                <el-descriptions-item label="区域面积">{{ currentArea.area }}平方公里</el-descriptions-item>
                <el-descriptions-item label="人口数量">{{ currentArea.population }}万人</el-descriptions-item>
                <el-descriptions-item label="检测点数量">{{ currentArea.testPoints }}个</el-descriptions-item>
                <el-descriptions-item label="本月检测量">{{ currentArea.testCount }}次</el-descriptions-item>
                <el-descriptions-item label="综合合格率">{{ (currentArea.passRate * 100).toFixed(1) }}%</el-descriptions-item>
                <el-descriptions-item label="不合格批次">{{ currentArea.abnormalCount }}批</el-descriptions-item>
              </el-descriptions>
            </el-tab-pane>
            <el-tab-pane label="指标详情" name="indicators">
              <el-table :data="indicatorTableData" stripe style="width: 100%">
                <el-table-column prop="name" label="检测指标" width="150" />
                <el-table-column prop="testCount" label="检测次数" width="120" />
                <el-table-column prop="passRate" label="合格率" width="150">
                  <template #default="{ row }">
                    <el-progress
                        :percentage="row.passRate * 100"
                        :color="getPassRateColor(row.passRate)"
                        :show-text="false"
                    />
                    <span style="margin-left: 8px">{{ (row.passRate * 100).toFixed(1) }}%</span>
                  </template>
                </el-table-column>
                <el-table-column prop="abnormalCount" label="不合格批次" width="120" />
              </el-table>
            </el-tab-pane>
          </el-tabs>
        </div>
      </div>
      <template #footer>
        <el-button @click="detailVisible = false">关闭</el-button>
        <el-button type="primary" @click="exportAreaData">导出区域数据</el-button>
      </template>
    </el-dialog>
  </div>
</template>
<script setup>
import { ref, onMounted, onBeforeUnmount, computed, nextTick } from 'vue'
import * as echarts from 'echarts'
import suzhouJson from '../../assets/suzhou.json'
import {
  foodSafetyIndicators,
  foodSafetyData,
  foodSafetyTrendData
} from '~/api/mock/data.js'
import {
  Refresh,
  Download,
  Calendar,
  Check,
  Warning,
  Search,
  Location
} from '@element-plus/icons-vue'
import { ElMessage } from 'element-plus'

// 数据引用
const indicators = foodSafetyIndicators
const tableData = ref([...foodSafetyData])
const trendData = ref({ ...foodSafetyTrendData })

// 当前选中的检测指标
const currentIndicator = ref('pesticide')

// 日期范围
const dateRange = ref([
  new Date(Date.now()  - 30 * 24 * 60 * 60 * 1000),
  new Date()
])

// 趋势图表相关
const trendType = ref('day')
const trendChart = ref(null)
const trendInstance = ref(null)

// 地图图表相关
const mapChart = ref(null)
const chartInstance = ref(null)

// 详情图表相关
const detailChart = ref(null)
const detailInstance = ref(null)
const detailVisible = ref(false)
const currentArea = ref({})
const detailTab = ref('basic')

// 表格相关
const tableSearch = ref('')
const currentPage = ref(1)
const pageSize = ref(10)
const totalItems = ref(0)
const loading = ref({
  table: false,
  chart: false
})

// 关键指标数据
const metrics = computed(() => {
  const totalTests = tableData.value.reduce((sum,  area) => sum + area.testCount,  0)
  const totalPasses = tableData.value.reduce((sum,  area) => sum + area.testCount  * area.passRate,  0)
  const totalAbnormal = tableData.value.reduce((sum,  area) => sum + (area.testCount  * (1 - area.passRate)),  0)
  const testPoints = tableData.value.reduce((sum,  area) => sum + area.testPoints,  0)

  return {
    totalTests,
    testChange: 5.8, // 模拟数据
    passRate: (totalPasses / totalTests * 100).toFixed(1),
    passRateChange: 2.3, // 模拟数据
    abnormalCount: Math.round(totalAbnormal),
    abnormalChange: -3.2, // 模拟数据
    testPoints,
    areaCoverage: tableData.value.length
  }
})

// 计算最大值用于颜色映射
const maxValue = computed(() => {
  return Math.max(...tableData.value.map(item  => item.testCount),  1)
})

// 图例数据
const legendData = computed(() => {
  const steps = 5
  const stepValue = maxValue.value  / steps
  return Array.from({  length: steps }, (_, i) => {
    const min = Math.floor(stepValue  * i)
    const max = Math.floor(stepValue  * (i + 1))
    return {
      name: i === steps - 1 ? `${min}+` : `${min}-${max}`,
      color: getColorByValue(min + 1)
    }
  }).reverse()
})

// 过滤后的表格数据
const filteredTableData = computed(() => {
  let filtered = tableData.value

  if (tableSearch.value)  {
    const search = tableSearch.value.toLowerCase()
    filtered = filtered.filter(item  =>
        item.name.toLowerCase().includes(search)
    )
  }

  totalItems.value  = filtered.length
  return filtered.slice(
      (currentPage.value  - 1) * pageSize.value,
      currentPage.value  * pageSize.value
  )
})

// 指标表格数据
const indicatorTableData = computed(() => {
  if (!currentArea.value.indicators)  return []

  return Object.entries(currentArea.value.indicators).map(([key,  value]) => ({
    name: indicators.find(i  => i.value  === key)?.label || key,
    testCount: value.testCount,
    passRate: value.passRate,
    abnormalCount: value.abnormalCount
  }))
})

// 初始化地图
const initMapChart = () => {
  if (chartInstance.value)  {
    chartInstance.value.dispose()
  }

  chartInstance.value  = echarts.init(mapChart.value)
  echarts.registerMap('suzhou',  suzhouJson)

  const option = {
    tooltip: {
      trigger: 'item',
      formatter: params => {
        if (params.seriesType  === 'map') {
          const data = tableData.value.find(item  => item.name  === params.name)  || {}
          return `
            <div style="font-weight:bold">${params.name}</div>
            <div>检测次数: ${data.testCount  || 0}</div>
            <div>合格率: ${data.passRate  ? (data.passRate  * 100).toFixed(1) + '%' : '无数据'}</div>
          `
        }
        return `${params.name}<br/> 检测次数: ${params.value[2]}`
      }
    },
    visualMap: {
      min: 0,
      max: maxValue.value,
      text: ['高', '低'],
      realtime: false,
      calculable: true,
      inRange: {
        color: ['#e0f3f8', '#abd9e9', '#74add1', '#4575b4', '#313695']
      },
      show: false
    },
    geo: {
      map: 'suzhou',
      roam: true,
      zoom: 1,
      label: {
        show: true,
        color: '#333',
        fontSize: 10
      },
      emphasis: {
        label: {
          color: '#fff',
          fontSize: 12
        },
        itemStyle: {
          areaColor: '#fe9929'
        }
      },
      itemStyle: {
        areaColor: '#e0f3f8',
        borderColor: '#999',
        borderWidth: 0.5
      }
    },
    series: [
      {
        name: '区域',
        type: 'map',
        map: 'suzhou',
        data: tableData.value.map(item  => ({
          name: item.name,
          value: item.testCount,
          itemStyle: {
            color: getColorByValue(item.testCount)
          }
        })),
        emphasis: {
          itemStyle: {
            areaColor: '#fe9929'
          }
        }
      },
      {
        name: '检测点',
        type: 'scatter',
        coordinateSystem: 'geo',
        data: tableData.value.map(item  => ({
          name: item.name,
          value: [item.lng, item.lat,  item.testCount],
          itemStyle: {
            color: getColorByValue(item.testCount)
          }
        })),
        symbolSize: val => {
          return Math.max(8,  Math.min(30,  val[2] / maxValue.value  * 30))
        },
        encode: {
          value: 2
        },
        label: {
          formatter: '{b}',
          position: 'right',
          show: false
        },
        emphasis: {
          label: {
            show: true
          }
        }
      }
    ]
  }

  chartInstance.value.setOption(option)
  chartInstance.value.on('click',  params => {
    if (params.data)  {
      const areaData = tableData.value.find(item  => item.name  === params.data.name)
      if (areaData) showDetail(areaData)
    }
  })
}

// 初始化趋势图
const initTrendChart = () => {
  if (trendInstance.value)  {
    trendInstance.value.dispose()
  }

  trendInstance.value  = echarts.init(trendChart.value)
  const currentTrend = trendData.value[trendType.value]

  const option = {
    tooltip: {
      trigger: 'axis',
      axisPointer: {
        type: 'cross',
        label: {
          backgroundColor: '#6a7985'
        }
      }
    },
    legend: {
      data: ['检测次数', '合格次数']
    },
    grid: {
      left: '3%',
      right: '4%',
      bottom: '3%',
      containLabel: true
    },
    xAxis: {
      type: 'category',
      boundaryGap: false,
      data: currentTrend.dates
    },
    yAxis: {
      type: 'value'
    },
    series: [
      {
        name: '检测次数',
        type: 'line',
        smooth: true,
        lineStyle: {
          width: 0
        },
        showSymbol: false,
        areaStyle: {
          opacity: 0.8,
          color: new echarts.graphic.LinearGradient(0,  0, 0, 1, [
            { offset: 0, color: 'rgba(58, 77, 233, 0.8)' },
            { offset: 1, color: 'rgba(58, 77, 233, 0.1)' }
          ])
        },
        emphasis: {
          focus: 'series'
        },
        data: currentTrend.tests
      },
      {
        name: '合格次数',
        type: 'line',
        smooth: true,
        lineStyle: {
          width: 0
        },
        showSymbol: false,
        areaStyle: {
          opacity: 0.8,
          color: new echarts.graphic.LinearGradient(0,  0, 0, 1, [
            { offset: 0, color: 'rgba(103, 194, 58, 0.8)' },
            { offset: 1, color: 'rgba(103, 194, 58, 0.1)' }
          ])
        },
        emphasis: {
          focus: 'series'
        },
        data: currentTrend.passes
      }
    ]
  }

  trendInstance.value.setOption(option)
}

// 初始化详情图表
const initDetailChart = () => {
  if (detailInstance.value)  {
    detailInstance.value.dispose()
  }

  detailInstance.value  = echarts.init(detailChart.value)
  const dates = currentArea.value.dailyData.map(item  =>
      new Date(item.date).toLocaleDateString()
  )

  const tests = currentArea.value.dailyData.map(item  => item.testCount)
  const passes = currentArea.value.dailyData.map(item  => item.passCount)
  const passRates = tests.map((test,  i) =>
      test > 0 ? (passes[i] / test) * 100 : 0
  )

  const option = {
    tooltip: {
      trigger: 'axis',
      axisPointer: {
        type: 'cross',
        label: {
          backgroundColor: '#6a7985'
        }
      }
    },
    legend: {
      data: ['检测次数', '合格次数', '合格率']
    },
    grid: {
      left: '3%',
      right: '4%',
      bottom: '3%',
      containLabel: true
    },
    xAxis: {
      type: 'category',
      boundaryGap: false,
      data: dates
    },
    yAxis: [
      {
        type: 'value',
        name: '次数',
        position: 'left'
      },
      {
        type: 'value',
        name: '合格率(%)',
        min: 0,
        max: 100,
        position: 'right'
      }
    ],
    series: [
      {
        name: '检测次数',
        type: 'bar',
        barWidth: '60%',
        data: tests,
        itemStyle: {
          color: '#5470C6'
        }
      },
      {
        name: '合格次数',
        type: 'bar',
        barWidth: '60%',
        data: passes,
        itemStyle: {
          color: '#91CC75'
        }
      },
      {
        name: '合格率',
        type: 'line',
        yAxisIndex: 1,
        smooth: true,
        lineStyle: {
          width: 3,
          color: '#EE6666'
        },
        showSymbol: false,
        data: passRates
      }
    ]
  }

  detailInstance.value.setOption(option)
}

// 更新趋势图表
const updateTrendChart = () => {
  initTrendChart()
}

// 处理指标变化
const handleIndicatorChange = () => {
  // 实际项目中这里可以根据指标筛选数据
  refreshData()
}

// 处理日期变化
const handleDateChange = () => {
  refreshData()
}

// 刷新数据
const refreshData = () => {
  loading.value.table  = true
  loading.value.chart  = true

  // 模拟API请求延迟
  setTimeout(() => {
    // 这里实际项目中应该调用API获取数据
    tableData.value  = [...foodSafetyData]
    trendData.value  = { ...foodSafetyTrendData }

    initMapChart()
    initTrendChart()

    loading.value.table  = false
    loading.value.chart  = false
  }, 800)
}

// 导出数据
const exportData = () => {
  loading.value.table  = true
  // 模拟导出延迟
  setTimeout(() => {
    const blob = new Blob([generateCSV()], { type: 'text/csv;charset=utf-8;' })
    const link = document.createElement('a')
    link.href  = URL.createObjectURL(blob)
    link.download  = `食品安全检测数据_${new Date().toISOString().slice(0, 10)}.csv`
    link.click()
    loading.value.table  = false

    ElMessage.success(' 数据导出成功')
  }, 1000)
}

// 导出区域数据
const exportAreaData = () => {
  const blob = new Blob([generateAreaCSV()], { type: 'text/csv;charset=utf-8;' })
  const link = document.createElement('a')
  link.href  = URL.createObjectURL(blob)
  link.download  = `${currentArea.value.name}_ 食品安全检测数据_${new Date().toISOString().slice(0, 10)}.csv`
  link.click()
  ElMessage.success(' 区域数据导出成功')
}

// 生成CSV数据
const generateCSV = () => {
  const headers = ['区域', '检测次数', '合格率', '不合格批次', '检测点数量']
  const rows = tableData.value.map(item  => [
    item.name,
    item.testCount,
    (item.passRate  * 100).toFixed(1) + '%',
    Math.round(item.testCount  * (1 - item.passRate)),
    item.testPoints
  ])

  return [headers, ...rows].map(row => row.join(',')).join('\n')
}

// 生成区域CSV数据
const generateAreaCSV = () => {
  const headers = ['日期', '检测次数', '合格次数', '合格率']
  const rows = currentArea.value.dailyData.map(item  => [
    new Date(item.date).toLocaleDateString(),
    item.testCount,
    item.passCount,
    (item.passCount  / item.testCount  * 100).toFixed(1) + '%'
  ])

  return [headers, ...rows].map(row => row.join(',')).join('\n')
}

// 显示区域详情
const showDetail = (area) => {
  currentArea.value  = { ...area }
  detailVisible.value  = true
  nextTick(() => {
    initDetailChart()
  })
}

// 处理搜索清除
const handleSearchClear = () => {
  tableSearch.value  = ''
  currentPage.value  = 1
}

// 处理排序变化
const handleSortChange = ({ prop, order }) => {
  if (!order) {
    tableData.value  = [...tableData.value].sort((a,  b) => a.name.localeCompare(b.name))
    return
  }

  tableData.value  = [...tableData.value].sort((a,  b) => {
    if (order === 'ascending') {
      return a[prop] > b[prop] ? 1 : -1
    } else {
      return a[prop] < b[prop] ? 1 : -1
    }
  })
}

// 处理分页大小变化
const handleSizeChange = (size) => {
  pageSize.value  = size
  currentPage.value  = 1
}

// 处理页码变化
const handlePageChange = (page) => {
  currentPage.value  = page
}

// 根据数值获取颜色
const getColorByValue = (value) => {
  const ratio = value / maxValue.value
  if (ratio > 0.8) return '#313695'
  if (ratio > 0.6) return '#4575b4'
  if (ratio > 0.4) return '#74add1'
  if (ratio > 0.2) return '#abd9e9'
  return '#e0f3f8'
}

// 获取合格率颜色
const getPassRateColor = (rate) => {
  if (rate > 0.9) return '#67C23A'
  if (rate > 0.8) return '#E6A23C'
  return '#F56C6C'
}

// 获取响应时间颜色
const getResponseTimeColor = (time) => {
  if (time < 2) return '#67C23A'
  if (time < 3) return '#E6A23C'
  return '#F56C6C'
}

// 获取数值标签类型
const getValueTagType = (value) => {
  const ratio = value / maxValue.value
  if (ratio > 0.7) return 'danger'
  if (ratio > 0.4) return 'warning'
  return 'success'
}

// 调整图表大小
const resizeCharts = () => {
  if (chartInstance.value)  chartInstance.value.resize()
  if (trendInstance.value)  trendInstance.value.resize()
  if (detailInstance.value)  detailInstance.value.resize()
}

onMounted(() => {
  initMapChart()
  initTrendChart()
  window.addEventListener('resize',  resizeCharts)
})

onBeforeUnmount(() => {
  window.removeEventListener('resize',  resizeCharts)
  if (chartInstance.value)  chartInstance.value.dispose()
  if (trendInstance.value)  trendInstance.value.dispose()
  if (detailInstance.value)  detailInstance.value.dispose()
})
</script>

<style scoped>
.food-safety-container {
  width: 100%;
  height: 100%;
  display: flex;
  flex-direction: column;
  background-color: #fff;
  border-radius: 8px;
  box-shadow: 0 2px 12px 0 rgba(0, 0, 0, 0.1);
  padding: 16px;
}

.header {
  display: flex;
  justify-content: space-between;
  align-items: center;
  margin-bottom: 20px;
}

.header-left h1 {
  font-size: 24px;
  color: #303133;
  margin: 0 0 8px 0;
}

.header-left {
  font-size: 14px;
  color: #909399;
}

.header-actions {
  display: flex;
  gap: 10px;
  align-items: center;
}

.metrics-row {
  display: grid;
  grid-template-columns: repeat(4, 1fr);
  gap: 16px;
  margin-bottom: 20px;
}

.metric-card {
  border-radius: 8px;
  border: none;
  transition: transform 0.3s ease;
}

.metric-card:hover {
  transform: translateY(-3px);
}

.metric-content {
  display: flex;
  align-items: center;
  padding: 16px;
}

.metric-icon {
  width: 48px;
  height: 48px;
  border-radius: 8px;
  display: flex;
  align-items: center;
  justify-content: center;
  margin-right: 16px;
  flex-shrink: 0;
}

.metric-info {
  flex: 1;
  min-width: 0;
}

.metric-title {
  font-size: 14px;
  color: #909399;
  margin-bottom: 4px;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

.metric-value {
  font-size: 24px;
  font-weight: 600;
  color: #303133;
  margin-bottom: 4px;
}

.metric-change {
  font-size: 12px;
  color: #909399;
  display: flex;
  align-items: center;
  gap: 4px;
}

.metric-change .up {
  color: #67C23A;
}

.metric-change .down {
  color: #F56C6C;
}

.chart-row {
  display: flex;
  gap: 16px;
  margin-bottom: 16px;
}

.chart-card {
  flex: 1;
  border-radius: 8px;
  border: none;
  transition: box-shadow 0.3s ease;
}

.chart-card:hover {
  box-shadow: 0 4px 12px rgba(0, 0, 0, 0.1) !important;
}

.map-card {
  display: flex;
  flex-direction: column;
}

.card-header {
  display: flex;
  justify-content: space-between;
  align-items: center;
  font-weight: 600;
  padding: 16px 20px;
}

.card-actions {
  display: flex;
  gap: 8px;
}

.map-chart, .trend-chart {
  width: 100%;
  height: 400px;
  background-color: #f9f9f9;
  border-radius: 4px;
}

.map-legend {
  display: flex;
  justify-content: center;
  gap: 20px;
  padding: 12px;
  background-color: #f5f7fa;
  border-radius: 4px;
  margin-top: 12px;
}

.legend-item {
  display: flex;
  align-items: center;
  gap: 6px;
}

.legend-color {
  display: inline-block;
  width: 16px;
  height: 16px;
  border-radius: 3px;
}

.legend-text {
  font-size: 12px;
  color: #666;
}

.table-card {
  margin-bottom: 20px;
  border-radius: 8px;
  border: none;
}

.table-actions {
  display: flex;
  gap: 12px;
}

.pagination-wrapper {
  margin-top: 16px;
  display: flex;
  justify-content: flex-end;
  padding: 0 16px 16px;
}

.detail-container {
  display: flex;
  gap: 16px;
}

.detail-chart {
  flex: 2;
}

.detail-info {
  flex: 1;
}

.detail-chart .chart {
  width: 100%;
  height: 400px;
}

.detail-tabs {
  height: 100%;
}

/* 响应式调整 */
@media (max-width: 1200px) {
  .metrics-row {
    grid-template-columns: repeat(2, 1fr);
  }

  .chart-row {
    flex-direction: column;
  }
}

@media (max-width: 768px) {
  .header {
    flex-direction: column;
    align-items: flex-start;
    gap: 16px;
  }

  .metrics-row {
    grid-template-columns: 1fr;
  }

  .detail-container {
    flex-direction: column;
  }
}
</style>